﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Data.OleDb;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using DotRas;
using System.Net.NetworkInformation;
using mshtml;
using System.Drawing.Imaging;

namespace PlateNumber {
    public partial class MainForm : Form {
        [DllImport("AspriseOCR.dll", EntryPoint = "OCR")]
        public static extern IntPtr OCR(string file, int type);

        [DllImport("AspriseOCR.dll", EntryPoint = "OCRpart")]
        static extern IntPtr OCRpart(string file, int type, int startX, int startY, int width, int height);

        [DllImport("AspriseOCR.dll", EntryPoint = "OCRBarCodes")]
        static extern IntPtr OCRBarCodes(string file, int type);

        [DllImport("AspriseOCR.dll", EntryPoint = "OCRpartBarCodes")]
        static extern IntPtr OCRpartBarCodes(string file, int type, int startX, int startY, int width, int height);

        private bool _documentCompleted = false;
        private bool _running = false;
        private bool _spying = false;
        //private int _step = 0;
        //private MonitorForm _monitor = null;
        private Option _option = null;
        private delegate void Worker();

        private int _currentIPUsingTimes = 0;

        // 拨号相关
        private string _currentIP = String.Empty;

        // 代理服务器相关
        private List<ProxyServer> _proxyServers = new List<ProxyServer>();
        private int _currentProxyServerIndex = -1;
        private int _proxyEnable = 0;
        private string _proxyServer = String.Empty;
        private bool _proxyServerHaveBeenChanged = false;
        private DateTime _proxyBeginTime = DateTime.MaxValue;

        private bool _delaying = false;


        //private string _clsbdh = "ENNNNNND6A8001313";  // 车辆识别代号
        //private string _hphm = "888CA";    // 预约号牌

        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern bool MessageBeep(uint uType);

        [DllImport(@"wininet",
            SetLastError = true,
            CharSet = CharSet.Auto,
            EntryPoint = "InternetSetOption",
            CallingConvention = CallingConvention.StdCall)]
        public static extern bool InternetSetOption(
            int hInternet,
            int dmOption,
            IntPtr lpBuffer,
            int dwBufferLength
        );


        public MainForm() {
            InitializeComponent();

            UpdateTo_1_2_12();

            webBrowser1.StatusTextChanged += new EventHandler(webBrowser1_StatusTextChanged);
            webBrowser1.DocumentTitleChanged += new EventHandler(webBrowser1_DocumentTitleChanged);
        }


        #region 升级

        private void UpdateTo_1_2_12() {
            OleDbConnection conn = new OleDbConnection(Program.ConnectionString);
            OleDbCommand cmd = new OleDbCommand("SELECT * FROM InvalidVIN WHERE ID=0", conn);
            try {
                conn.Open();
                cmd.ExecuteNonQuery();
            }
            catch {
                // 没发现 InvalidVIN 表，创建之
                cmd = new OleDbCommand("CREATE TABLE InvalidVIN([Id] COUNTER NOT NULL, [VIN] TEXT(255) NULL)", conn);
                cmd.ExecuteNonQuery();
            }
            finally {
                conn.Close();
            }
        }

        #endregion


        #region 事件

        private void MainForm_Load(object sender, EventArgs e) {
            //ValidationForm form = new ValidationForm();
            //form.ValidationImage = Image.FromFile(Application.StartupPath + "\\untitled.bmp");
            //form.ShowDialog();

            //--pictureBox1.Visible = false;
            //System.Windows.Forms.Form.CheckForIllegalCrossThreadCalls = false;
            toolStripStatusLabel1.Text = String.Empty;
            //webBrowser1.Navigate("http://" + _option.General.Domain + "/wscgs/");

            //--Thread t = new Thread(new ThreadStart(Init));
            //--t.IsBackground = true;
            //--t.Start();
            //--timer1.Start();
            Init();
            //webBrowser1.Navigate(_option.General.Home); // 删除
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e) {
            Exit();
        }

        // 开始
        private void tssbStart_ButtonClick(object sender, EventArgs e) {
            Start(false);
        }

        // 开始(探测模式)
        private void tsmiStartSpy_Click(object sender, EventArgs e) {
            Start(true);
        }

        // 停止
        private void tsbStop_Click(object sender, EventArgs e) {
            Stop();
        }

        // 数据管理
        private void toolStripButton2_Click(object sender, EventArgs e) {
            DataForm form = new DataForm();
            form.ShowDialog(this);
        }

        // VIN 生成器
        private void toolStripButton3_Click(object sender, EventArgs e) {
            VINGenForm form = new VINGenForm();
            form.Show(this);
        }

        // 选项
        private void tsbOption_Click(object sender, EventArgs e) {
            OptionForm frm = new OptionForm();
            if (frm.ShowDialog(this) == DialogResult.OK) {
                _option = frm.Option;

                UpdateNetworkConnectionStatus();

                if (_option.Network.ConnectionType == NetworkConnectionType.Proxy &&
                    tssbStart.Enabled == true) {
                    CheckProxyServerResources();
                }
            }
        }

        private void webBrowser1_DocumentTitleChanged(object sender, EventArgs e) {
            if (!String.IsNullOrEmpty(webBrowser1.DocumentTitle)) {
                this.Text = Application.ProductName + " (版本: " + Application.ProductVersion + ")" + " - " + webBrowser1.DocumentTitle;
            }
        }

        private void webBrowser1_StatusTextChanged(object sender, EventArgs e) {
            toolStripStatusLabel1.Text = webBrowser1.StatusText;
        }

        private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e) {
            _documentCompleted = false;
            if (_option.Network.ConnectionType == NetworkConnectionType.Proxy) {
                _proxyBeginTime = DateTime.Now;
            }
            UpdateUI();
        }

        private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e) {

        }

        private void webBrowser1_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e) {
            toolStripProgressBar1.Maximum = (int)e.MaximumProgress;
            toolStripProgressBar1.Value = (int)e.CurrentProgress;
        }

        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
            if (webBrowser1.ReadyState != WebBrowserReadyState.Complete) {
                return;
            }

            //MessageBox.Show(webBrowser1.Document.Body.InnerHtml);
            _documentCompleted = true;

            if (_option.Network.ConnectionType == NetworkConnectionType.Proxy) {
                int delay = (int)DateTime.Now.Subtract(_proxyBeginTime).TotalSeconds;
                ProxyServer.SetDelay(_proxyServers[_currentProxyServerIndex].Id, delay);

                if (webBrowser1.Document.Body.InnerHtml.Contains("网络忙") || webBrowser1.Document.Body.InnerHtml.Contains("无法显示")) {
                    ProxyServer.SetSign(_proxyServers[_currentProxyServerIndex].Id, ProxyServerSign.Invalid);
                    ChangeProxyServer();
                    Restart();
                }
                else {
                    if (delay < _option.Network.StaticProxyServerResponseTime) {
                        ProxyServer.SetSign(_proxyServers[_currentProxyServerIndex].Id, ProxyServerSign.Static);
                    }
                    if (delay > _option.Network.InvalidProxyServerResponseTime) {
                        ProxyServer.SetSign(_proxyServers[_currentProxyServerIndex].Id, ProxyServerSign.Invalid);
                        ChangeProxyServer();
                        Restart();
                    }
                }
            }

            // 伪装IP
            //if (webBrowser1.Document.Forms.Count > 0) {
            //    if (webBrowser1.Document.Forms[0].All["ip"] != null) {
            //        webBrowser1.Document.Forms[0].All["ip"].SetAttribute("value", GetMockIP());
            //    }
            //}

            UpdateUI();
        }

        // 计时器（时间间隔：5秒）
        private void timer1_Tick(object sender, EventArgs e) {
            //--pictureBox1.Visible = true;
            //Log("正在搜索代理服务器...");
            //int page = 1;
            //int sum = 0;
            //int count = 0;
            //while ((count = ProxyUpdater(page)) >= 0) {
            //    ++page;
            //    sum += count;
            //}
            //Log("新增 " + sum + " 个代理服务器。");
            //--pictureBox1.Visible = false;
            UpdateNetworkConnectionStatus();
        }

        #endregion


        #region 操作

        // 初始化
        private void Init() {
            this.Text = Application.ProductName + " (版本: " + Application.ProductVersion + ")";
            tsbStop.Enabled = false;
            tsbRedial.Enabled = false;
            picProcessing.Visible = false;

            _option = Option.Load();

            if (_option.Network.ConnectionType == NetworkConnectionType.Proxy) {
                CheckProxyServerResources();
            }


            lvNetwork.Items.Clear();
            lvNetwork.Items.Add(new ListViewItem(new[] { "连接类型:", String.Empty }));
            lvNetwork.Items.Add(new ListViewItem(new[] { "连接状态:", String.Empty }));
            lvNetwork.Items.Add(new ListViewItem(new[] { "连接名称:", String.Empty }));
            lvNetwork.Items.Add(new ListViewItem(new[] { "服务器IP:", String.Empty }));
            lvNetwork.Items.Add(new ListViewItem(new[] { "客户端IP:", String.Empty }));

            timer1.Start();
            UpdateNetworkConnectionStatus();
            //Log("初始化完成");
        }

        // 退出
        private void Exit() {
            //ResetIEProxy();
            ClearProxyServer();
            _running = false;
            timer1.Stop();
        }

        // 开始
        private void Start(bool spying) {
            try {
                if (!_running) {
                    _running = true;
                    _spying = spying;
                    _documentCompleted = false;

                    if (_option.Network.ConnectionType == NetworkConnectionType.Proxy) {
                        _proxyServers = ProxyServer.GetAvailableProxyServers();
                        _currentProxyServerIndex = -1;
                    }
                    Restart();

                    Thread t = new Thread(DoWork);
                    t.IsBackground = true;
                    t.Start();

                    tssbStart.Enabled = false;
                    tsbStop.Enabled = true;
                    tsbOption.Enabled = false;

                    if (_option.Network.ConnectionType == NetworkConnectionType.Ppp) {
                        tsbRedial.Enabled = true;
                    }
                }
            }
            catch (Exception ex) {
                Stop();
                Log("启动失败：" + ex.Message);
            }
        }

        // 停止
        private void Stop() {
            ClearProxyServer();
            _running = false;

            tssbStart.Enabled = true;
            tsbStop.Enabled = false;
            tsbOption.Enabled = true;

            if (_option.Network.ConnectionType == NetworkConnectionType.Ppp) {
                tsbRedial.Enabled = false;
            }
        }

        // 更新窗口
        private void UpdateUI() {
            toolStripProgressBar1.Visible = !_documentCompleted;
        }


        //private void ddlAdapters_SelectedIndexChanged(object sender, EventArgs e) {
        //    UpdateAdapterInfo(ddlAdapters.SelectedItem.ToString());
        //}

        //private void UpdateAdapterInfo(string name){
        //    lvNetwork.Items[0].SubItems[1].Text = String.Empty;
        //    lvNetwork.Items[1].SubItems[1].Text = String.Empty;
        //    lvNetwork.Items[2].SubItems[1].Text = String.Empty;
        //    lvNetwork.Items[3].SubItems[1].Text = String.Empty;
        //    lvNetwork.Items[4].SubItems[1].Text = String.Empty;

        //    NetworkInterface[] nis = NetworkInterface.GetAllNetworkInterfaces();
        //    foreach (NetworkInterface ni in nis) {
        //        if (ni.Name == name) {
        //            lvNetwork.Items[0].SubItems[1].Text = ni.Description;

        //            lvNetwork.Items[1].SubItems[1].Text = ni.NetworkInterfaceType.ToString();

        //            if (ni.GetIPProperties().UnicastAddresses.Count > 0) {
        //                lvNetwork.Items[2].SubItems[1].Text = ni.GetIPProperties().UnicastAddresses[0].Address.ToString();
        //            }

        //            if (ni.GetIPProperties().GatewayAddresses.Count > 0) {
        //                lvNetwork.Items[3].SubItems[1].Text = ni.GetPhysicalAddress().ToString();
        //            }


        //        }
        //    }
        //}

        // 更新网络状态
        private void UpdateNetworkConnectionStatus() {
            lvNetwork.Items[0].SubItems[1].Text = String.Empty;
            lvNetwork.Items[1].SubItems[1].Text = String.Empty;
            lvNetwork.Items[2].SubItems[1].Text = String.Empty;
            lvNetwork.Items[3].SubItems[1].Text = String.Empty;
            lvNetwork.Items[4].SubItems[1].Text = String.Empty;

            switch (_option.Network.ConnectionType) {
                case NetworkConnectionType.Local:   // 本地连接
                    lvNetwork.Items[0].SubItems[1].Text = "本地连接";
                    //if (NetworkInterface.GetIsNetworkAvailable()) {
                    //    NetworkInterface[] nis = NetworkInterface.GetAllNetworkInterfaces();
                    //    foreach (NetworkInterface ni in nis) {
                    //        if (ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet &&
                    //            ni.OperationalStatus == OperationalStatus.Up) {
                    //            lvNetwork.Items[1].SubItems[1].Text = "已连接";
                    //            lvNetwork.Items[2].SubItems[1].Text = ni.Name;
                    //            foreach (var ip in ni.GetIPProperties().UnicastAddresses) {
                    //                if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) {
                    //                    lvNetwork.Items[4].SubItems[1].Text = ip.Address.ToString();
                    //                    break;
                    //                }
                    //            }
                    //            break;
                    //        }
                    //    }
                    //}
                    //else {
                    //    lvNetwork.Items[1].SubItems[1].Text = "已断开连接";
                    //}
                    break;

                case NetworkConnectionType.Proxy:   // 代理服务器
                    lvNetwork.Items[0].SubItems[1].Text = "代理服务器(" + _proxyServers.Count + ")";
                    if (!String.IsNullOrEmpty(_currentIP)) {
                        lvNetwork.Items[3].SubItems[1].Text = _currentIP + "(" + _currentIPUsingTimes + ")";
                    }
                    break;

                case NetworkConnectionType.Ppp:     // 拨号连接
                    lvNetwork.Items[0].SubItems[1].Text = "拨号连接";
                    lvNetwork.Items[1].SubItems[1].Text = "已断开连接";

                    PPP ppp = PPP.GetDefault();

                    RasConnection conn = RasConnection.GetActiveConnectionByName(ppp.EntryName, RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.User));
                    if (conn == null) {
                        conn = RasConnection.GetActiveConnectionByName(ppp.EntryName, RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.AllUsers));
                    }
                    if (conn != null) {
                        lvNetwork.Items[1].SubItems[1].Text = "已连接";
                        lvNetwork.Items[2].SubItems[1].Text = conn.EntryName;
                        RasIPInfo info = (RasIPInfo)conn.GetProjectionInfo(RasProjectionType.IP);
                        lvNetwork.Items[3].SubItems[1].Text = info.ServerIPAddress.ToString();
                        lvNetwork.Items[4].SubItems[1].Text = info.IPAddress.ToString() + "(" + _currentIPUsingTimes + ")";
                    }
                    break;
            }
        }

        // 更新任务状态
        private void UpdateTaskStatus(int index, string status) {

            if (lvTask.Items[index].SubItems.Count == 1) {
                lvTask.Items[index].SubItems.Add(status);
            }
            else {
                lvTask.Items[index].SubItems[1].Text = status;
            }
        }

        // 生成伪造IP
        private string GetMockIP() {
            long tick = DateTime.Now.Ticks;
            Random rand = new Random((int)(tick & 0xffffffffL) | (int)(tick >> 32));
            string ip = rand.Next(1, 254) + "." + rand.Next(1, 254) + "." + rand.Next(1, 254) + "." + rand.Next(1, 254);
            return ip;
        }

        // 日志
        private void Log(string log) {
            //--txtLog.Text += "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "]" + Environment.NewLine + log + Environment.NewLine + Environment.NewLine;
            //--txtLog.SelectionStart = txtLog.Text.Length;
            //--txtLog.ScrollToCaret();
            lvLog.Items.Add(new ListViewItem(new[] { log, DateTime.Now.ToString("HH:mm:ss") }));
            lvLog.AutoResizeColumn(0, ColumnHeaderAutoResizeStyle.ColumnContent);
            lvLog.Items[Math.Max(0, lvLog.Items.Count - 1)].EnsureVisible();
        }

        // 重新开始
        private void Restart() {
            if (!_running) {
                return;
            }

            switch (_option.Network.ConnectionType) {
                case NetworkConnectionType.Local:
                    break;
                case NetworkConnectionType.Proxy:
                    if (_currentIPUsingTimes == 0 || _currentIPUsingTimes >= _option.Task.IPSwitchPeriod) {
                        // 更换代理服务器
                        ChangeProxyServer();
                        _currentIPUsingTimes = 1;
                    }
                    else {
                        ++_currentIPUsingTimes;
                    }
                    break;
                case NetworkConnectionType.Ppp:
                    if (_currentIPUsingTimes == 0 || _currentIPUsingTimes >= _option.Task.IPSwitchPeriod) {
                        // 重新拨号
                        Redial();
                        _currentIPUsingTimes = 1;
                    }
                    else {
                        ++_currentIPUsingTimes;
                    }
                    break;
            }

            webBrowser1.Navigate(_option.General.Home);
        }

        // 延时
        private void Delay(int seconds) {
            Thread.Sleep(seconds * 1000);
        }


        //////////////////////////////////////////////////
        //
        // 代理服务器
        //

        // 检查代理服务资源
        private void CheckProxyServerResources() {
            if (_option.Network.ConnectionType == NetworkConnectionType.Proxy) {
                _proxyServers = ProxyServer.GetAvailableProxyServers();

                if (_proxyServers.Count < _option.Network.AvailableProxyServerCountLowLimit) {
                    tssbStart.Enabled = false;
                    picProcessing.Visible = true;
                    Log("正在获取代理服务器资源...");
                    Thread t = new Thread(new ThreadStart(UpdateProxyServers));
                    t.IsBackground = true;
                    t.Start();
                }
            }
        }

        // 更新代理服务器
        private void UpdateProxyServers() {
            int page = 1;
            int sum = 0;
            int count = 0;

            while ((count = ProxyServerUpdater(page)) >= 0) {
                ++page;
                sum += count;
                _proxyServers = ProxyServer.GetAvailableProxyServers();
            }

            _currentProxyServerIndex = -1;

            this.Invoke(new Worker(delegate() {
                if (_proxyServers.Count > 0) {
                    tssbStart.Enabled = true;
                    Log("新增 " + sum + " 个代理服务器");
                }
                else {
                    tssbStart.Enabled = false;
                    Log("没有获取到新的代理服务器");
                }
                picProcessing.Visible = false;
            }));
        }

        private int ProxyServerUpdater(int page) {
            try {
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(
                    "http://www.proxy114.com/proxy/transparent-" + page.ToString() + ".html");
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                string html = String.Empty;
                using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
                    html = reader.ReadToEnd();
                }
                //MessageBox.Show("D:\\proxy.txt");
                //StreamWriter writer = new StreamWriter(Directory.GetDirectoryRoot(Application.ExecutablePath) + "\\proxy.txt");
                //writer.Write(html);
                //writer.Close();

                // IP
                MatchCollection ips = Regex.Matches(html,
                        @"i\[\d+\]=[\'\""]*(\d+\.\d+\.\d+\.\d+)[\''\""]*",
                        RegexOptions.Multiline);
                // 端口
                MatchCollection ports = Regex.Matches(html,
                        @"p\[\d+\]=[\'\""]*(\d+)[\''\""]*",
                        RegexOptions.Multiline);
                //// 类型
                //MatchCollection types = Regex.Matches(html,
                //        @"t\[(\d+)\]=[\'\""]*(\w+)[\''\""]*",
                //        RegexOptions.Multiline);
                // 国家
                MatchCollection countries = Regex.Matches(html,
                        @"c\[\d+\]=[\'\""]*(\w+)[\''\""]*",
                        RegexOptions.Multiline);
                // 更新日期
                MatchCollection updates = Regex.Matches(html,
                        @"d\[\d+\]=[\''\""]*(\d+\-\d+\-\d+\s+\d+:\d+:\d+)[\''\""]*",
                        RegexOptions.Multiline);

                int count = 0;
                using (OleDbConnection conn = new OleDbConnection(Program.ConnectionString)) {
                    conn.Open();

                    if (ips != null && ips.Count > 0) {
                        ProxyServer[] proxies = new ProxyServer[ips.Count];
                        for (int i = 0; i < proxies.Length; ++i) {
                            if (ProxyServer.Save(new ProxyServer() {
                                Id = 0,
                                Ip = ips[i].Groups[1].Value,
                                Port = Int32.Parse(ports[i].Groups[1].Value),
                                Country = countries[i].Groups[1].Value,
                                UpdateDate = DateTime.Parse(updates[i].Groups[1].Value),
                                Delay = Int32.MaxValue,
                                Sign = ProxyServerSign.Normal
                            })) {
                                ++count;
                            }

                            //// 不能在无效代理表里
                            //int invalidProxiesCount = 0;
                            //using (OleDbCommand cmd = new OleDbCommand("SELECT COUNT(*) FROM InvalidProxies WHERE IP=@IP AND Port=@Port", conn)) {
                            //    cmd.Parameters.AddWithValue("@IP", ips[i].Groups[1].Value);
                            //    cmd.Parameters.AddWithValue("@Port", Int32.Parse(ports[i].Groups[1].Value));
                            //    invalidProxiesCount = (int)cmd.ExecuteScalar();
                            //}

                            //if (invalidProxiesCount == 0) {
                            //    ProxyServer proxy = new ProxyServer() {
                            //        Ip = ips[i].Groups[1].Value,
                            //        Port = Int32.Parse(ports[i].Groups[1].Value),
                            //        Country = countries[i].Groups[1].Value,
                            //        UpdateDate = DateTime.Parse(updates[i].Groups[1].Value)
                            //    };
                            //    if (!_proxyServers.Contains(proxy)) {
                            //        _proxyServers.Add(proxy);
                            //        ++count;
                            //    }
                            //}
                        }
                    }
                } // using conn

                return count;
            }
            catch (Exception ex) {
                //this.Invoke(new Worker(delegate()
                //{
                Log(ex.Message);
                //}));
                return -1;
            }
        }

        // 更换代理服务器
        private void ChangeProxyServer() {
            ++_currentProxyServerIndex;
            if (_currentProxyServerIndex >= _proxyServers.Count) {
                _currentProxyServerIndex = 0;
            }

            //打开注册表
            RegistryKey regKey = Registry.CurrentUser;
            string SubKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings";
            RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true);

            if (!_proxyServerHaveBeenChanged) {
                // 第一次设置代理服务器，保存IE原始代理设置
                _proxyEnable = Int32.Parse(optionKey.GetValue("ProxyEnable").ToString());
                _proxyServer = optionKey.GetValue("ProxyServer").ToString();
            }

            //更改健值，设置代理
            optionKey.SetValue("ProxyEnable", 1);
            optionKey.SetValue("ProxyServer", _proxyServers[_currentProxyServerIndex].Ip + ":" + _proxyServers[_currentProxyServerIndex].Port);

            ////激活代理设置
            //InternetSetOption(0, 39, IntPtr.Zero, 0);
            //InternetSetOption(0, 37, IntPtr.Zero, 0);

            optionKey.Close();
            regKey.Close();

            _proxyServerHaveBeenChanged = true;
            _currentIP = _proxyServers[_currentProxyServerIndex].Ip + ":" + _proxyServers[_currentProxyServerIndex].Port;

            //--lblProxyIP.Text = "服务器: " + _proxyServers[_proxyIndex].IP + ":" + _proxyServers[_proxyIndex].Port;
            //--lblProxyCountry.Text = "位置: " + _proxyServers[_proxyIndex].Country;
        }

        // 清除IE的代理服务器设置
        private void ClearProxyServer() {
            //打开注册表
            RegistryKey regKey = Registry.CurrentUser;
            string SubKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Internet Settings";
            RegistryKey optionKey = regKey.OpenSubKey(SubKeyPath, true);

            // 还原IE原始设置
            if (_proxyServerHaveBeenChanged) {
                optionKey.SetValue("ProxyEnable", _proxyEnable);
                optionKey.SetValue("ProxyServer", _proxyServer);
            }

            optionKey.Close();
            regKey.Close();

            ////激活代理设置
            //InternetSetOption(0, 39, IntPtr.Zero, 0);
            ////InternetSetOption(0, 37, IntPtr.Zero, 0);
        }

        //private void RemoveCurrentIEProxy() {
        //    if (_currentProxyServerIndex > 0 && _proxyServers.Count > _currentProxyServerIndex - 1) {
        //        Log(_proxyServers[_currentProxyServerIndex - 1].Ip + ":" + _proxyServers[_currentProxyServerIndex - 1].Port + "(" + _proxyServers[_currentProxyServerIndex - 1].Country + ") 无效，已被删除。");

        //        OleDbConnection conn = new OleDbConnection(Program.ConnectionString);
        //        OleDbCommand cmd = new OleDbCommand("INSERT INTO InvalidProxies(IP, Port) VALUES(@IP, @Port)", conn);
        //        cmd.Parameters.AddWithValue("@IP", _proxyServers[_currentProxyServerIndex - 1].Ip);
        //        cmd.Parameters.AddWithValue("@Port", _proxyServers[_currentProxyServerIndex - 1].Port);
        //        using (conn) {
        //            conn.Open();
        //            cmd.ExecuteNonQuery();
        //        }

        //        _proxyServers.RemoveAt(_currentProxyServerIndex - 1);
        //        --_currentProxyServerIndex;
        //    }

        //    //--lblProxyCount.Text = "数量: " + _proxyServers.Count;
        //}


        //////////////////////////////////////////////////
        //
        // 拨号连接
        //

        private void Redial() {
            Log("重新拨号");

            // 断开
            HangUp();

            // 拨号
            Dial();
        }

        private void Dial() {
            PPP ppp = PPP.GetDefault();

            RasConnection conn = RasConnection.GetActiveConnectionByName(ppp.EntryName, RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.User));
            if (conn == null) {
                conn = RasConnection.GetActiveConnectionByName(ppp.EntryName, RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.AllUsers));
            }

            if (conn == null) {
                RasDialer dialer = new RasDialer();
                dialer.EntryName = ppp.EntryName;
                dialer.Credentials = new NetworkCredential(ppp.UserName, ppp.Password);
                dialer.PhoneNumber = ppp.PhoneNumber;
                dialer.Timeout = 1000;
                RasHandle handle = dialer.Dial();

                RasIPInfo ip = (RasIPInfo)RasConnection.GetActiveConnectionByHandle(handle).GetProjectionInfo(RasProjectionType.IP);
                _currentIP = ip.IPAddress.ToString();
            }


            UpdateNetworkConnectionStatus();
        }

        private void HangUp() {
            PPP ppp = PPP.GetDefault();

            RasConnection conn = RasConnection.GetActiveConnectionByName(ppp.EntryName, RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.User));
            if (conn == null) {
                conn = RasConnection.GetActiveConnectionByName(ppp.EntryName, RasPhoneBook.GetPhoneBookPath(RasPhoneBookType.AllUsers));
            }

            if (conn != null) {
                conn.HangUp();
            }

            UpdateNetworkConnectionStatus();
        }

        #endregion


        #region 程序核心

        private void DoWork() {
            if (this == null || this.IsDisposed) {
                return;
            }

            this.Invoke(new Worker(delegate() {
                //_monitor = new MonitorForm();
                //_monitor.Show(this);
                Log("任务开始" + (_spying ? "(探测模式)" : String.Empty));

                //toolStripButton1.Image = imageList1.Images[1];
                //toolStripButton4.Enabled = false;
            }));

            int testPos = 0;        // 测试游标
            int formalPos = 0;      // 正式游标
            int step = 0;           // 当前步骤
            int testCount = 0;      // 车辆标识号的测试次数，0 表示需要重新生成车辆标识号
            string testVIN = String.Empty;  // 用于测试的车辆标识号
            int succeedCount = 0;   // 成功预约计数
            //bool needDelay = false;   // 是否产生操作延时
            int ifFoundUnknownPageRetryTimes = 0;
            int ifNumberNotExistRetryTimes = 0;
            int ifNumberHasBeUsedRetryTimes = 0;

            DataTable dtTest = null;    // 测试队列
            DataTable dtFormal = null;  // 正式队列

            // 将以前过期的数据标记为“等待预约”
            OleDbConnection connUpdate = new OleDbConnection(Program.ConnectionString);
            OleDbCommand cmdUpdate1 = new OleDbCommand("UPDATE Test SET State = 0 WHERE State = -1 AND DateDiff('d', SubmitDate, Now) > 0", connUpdate);
            OleDbCommand cmdUpdate2 = new OleDbCommand("UPDATE Formal SET State = 0 WHERE State = -1 AND DateDiff('d', SubmitDate, Now) > 0", connUpdate);
            using (connUpdate) {
                connUpdate.Open();
                cmdUpdate1.ExecuteNonQuery();
                cmdUpdate2.ExecuteNonQuery();
            }

            // 填充测试队列
            OleDbDataAdapter daTest = new OleDbDataAdapter(
                "SELECT * FROM Test WHERE Invalid <> True AND (State = 0 OR State = -2)",
                Program.ConnectionString);
            dtTest = new DataTable();
            using (daTest) {
                daTest.Fill(dtTest);
            }

            // 填充正式队列（等待预约、号牌不存在、已被预约）
            OleDbDataAdapter daFormal = new OleDbDataAdapter(
                "SELECT * FROM Formal WHERE Invalid <> True AND (State = 0 OR State = -2 OR State = -3)",
                Program.ConnectionString);
            dtFormal = new DataTable();
            using (daFormal) {
                daFormal.Fill(dtFormal);
            }

            testPos = 0;        // 测试游标
            formalPos = 0;      // 正式游标
            step = 0;           // 当前步骤

            while (_running) {
                if (this == null || this.IsDisposed) {
                    return;
                }

                if (_spying) {
                    if (dtTest.Rows.Count == 0) {
                        break;
                    }
                    if (testPos >= dtTest.Rows.Count) {
                        if (!_option.Task.CirculateTaskList) {
                            break;
                        }
                        else {
                            testPos = 0;
                        }
                    }
                }
                else {
                    if (dtFormal.Rows.Count == 0) {
                        break;
                    }
                    if (formalPos >= dtFormal.Rows.Count) {
                        if (!_option.Task.CirculateTaskList) {
                            break;
                        }
                        else {
                            formalPos = 0;
                        }
                    }
                }

                if (testCount == 0) {
                    testVIN = VINGenerator.Generate();
                    testCount = 1;
                }

                if (_documentCompleted) {
                    //switch (step) {
                    //    case 1: // 机动车信息录入
                    //    //case 2: // 预选号牌
                    //    case 4: // 选号完成
                    //        // 延时
                    //        needDelay = true;
                    //        break;
                    //    case 3:
                    //        this.Invoke(new Worker(delegate() {
                    //            if (webBrowser1.Document.Body.InnerHtml.Contains("请尽快点击“确认”按钮完成选号")) {
                    //                // 号牌可以预选时延时
                    //                needDelay = true;
                    //            }
                    //            else {
                    //                // 不存在、被预约时不延时
                    //                needDelay = false;
                    //            }
                    //        }));
                    //        break;
                    //    default:
                    //        // 不延时
                    //        needDelay = false;
                    //        break;
                    //}

                    //if (_delaying) {
                    //    switch (step) {
                    //        case 0:
                    //            Delay(_option.Task.Step0Delay);
                    //            break;
                    //        case 1:
                    //            Delay(_option.Task.Step1Delay);
                    //            break;
                    //        case 2:
                    //            Delay(_option.Task.Step2Delay);
                    //            break;
                    //        case 3:
                    //            Delay(_option.Task.Step3Delay);
                    //            break;
                    //        case 4:
                    //            Delay(_option.Task.Step4Delay);
                    //            break;
                    //        default:
                    //            _delaying = false;
                    //            break;
                    //    }
                    //}

                    // 真正干活的地方
                    this.Invoke(new Worker(delegate() {
                        try {
                            HtmlDocument doc = webBrowser1.Document;

                            //if (doc.Body.InnerHtml.Contains("网络忙") || doc.Body.InnerHtml.Contains("无法显示")) {
                            //    Log("网络忙，任务被终止");
                            //    step = 0;
                            //    Stop();
                            //    return;
                            //}

                            if (doc.Body.InnerHtml.Contains("每个电脑的IP查询次数最多为15次，您的电脑在网上多次占用号牌，为网上选号公平公正，您的电脑已被禁止选号功能，请明天再来重新预选")) {
                                if (!String.IsNullOrEmpty(_currentIP)) {
                                    Log(_currentIP + " 已达到今天的使用上限，更换IP后任务重新开始。");
                                    ProxyServer.SetTodayCanNotBeUse(_proxyServers[_currentProxyServerIndex].Id);
                                    _proxyServers.RemoveAt(_currentProxyServerIndex);
                                    _currentProxyServerIndex -= 1;
                                    _currentIPUsingTimes = 0;
                                    step = 0;
                                    Restart();
                                    return;
                                }
                            }

                            if (doc.Body.InnerHtml.Contains("车辆识别代号非法")) {
                                Log("车辆识别代号非法，任务重新开始");
                                // 继续下一个
                                if (_spying) {
                                    ++testPos;
                                }
                                else {
                                    ++formalPos;
                                }
                                //Delay(_option.Task.Step0Delay);
                                step = 0;
                                Restart();
                                return;
                            }

                            if (doc.Body.InnerHtml.Contains("车辆识别代号已被锁定")) {
                                OleDbConnection conn = new OleDbConnection(Program.ConnectionString);
                                OleDbCommand cmd = new OleDbCommand("INSERT INTO InvalidVIN(VIN) VALUES(@VIN)", conn);
                                cmd.Parameters.AddWithValue("@VIN", testVIN.Substring(0, 6));
                                using (conn) {
                                    conn.Open();
                                    cmd.ExecuteNonQuery();
                                }

                                Log("车辆识别代号已被锁定，" + testVIN + " 已被加入排除名单，任务重新开始");
                                //Delay(_option.Task.Step0Delay);
                                testCount = 0;
                                step = 0;
                                //Restart();
                                webBrowser1.Navigate("http://" + _option.General.Domain + "/ixh/ywlxqd.jsp");
                                return;
                            }



                            //////////////////////////////////////////////////
                            //
                            // 阅读说明
                            //

                            if (webBrowser1.Document.Body.InnerHtml.Contains("机动车网上预选号说明")) {//step == 0 && webBrowser1.Url.ToString().ToLower() == "http://" + _option.General.Domain + "/ixh/cx.do") {                                
                                if (doc.Forms[0] == null) { // "cxForm"
                                    return;
                                }

                                // 延时
                                if (_option.Task.Step0Delay > 0 && !_delaying) {
                                    _delaying = true;
                                    return;
                                }
                                else {
                                    _delaying = false;
                                }

                                if (doc.Forms[0].All["tyan"].GetAttribute("value") == "同 意") {  // "cxForm"
                                    //
                                    // 显示任务状态
                                    //

                                    // 任务模式
                                    UpdateTaskStatus(0, _spying ? "探测模式" : "正常模式");
                                    // 测试 VIN
                                    UpdateTaskStatus(1, testVIN);
                                    //测试次数
                                    UpdateTaskStatus(2, testCount.ToString());
                                    // 正式 VIN
                                    UpdateTaskStatus(3, _spying ? String.Empty : dtFormal.Rows[formalPos]["VIN"].ToString());
                                    // 预选号牌
                                    UpdateTaskStatus(4, _spying ? dtTest.Rows[testPos]["PlateNumber"].ToString() : dtFormal.Rows[formalPos]["PlateNumber"].ToString());
                                    // 任务队列
                                    UpdateTaskStatus(5, !_spying ? ((formalPos + 1) + " / " + dtFormal.Rows.Count) : ((testPos + 1) + " / " + dtTest.Rows.Count));


                                    // 提交
                                    step = 1;
                                    doc.Forms[0].All["state"].SetAttribute("value", String.Empty);  // "cxForm"
                                    doc.Forms[0].All["type"].SetAttribute("value", "loadRegister"); // qdsj 2011-10-8 // "cxForm"
                                    doc.Forms[0].All["step"].SetAttribute("value", "2");  // "cxForm"   2011-10-8
                                    doc.Forms[0].InvokeMember("submit");    // "cxForm"
                                }

                                return;
                            }


                            //////////////////////////////////////////////////
                            //
                            // 机动车信息录入
                            //

                            if (webBrowser1.Document.Body.InnerHtml.Contains("请正确输入相关信息，否则选号无效")) {//step == 1 && webBrowser1.Url.ToString().ToLower() == "http://" + _option.General.Domain + "/ixh/register.do") {
                                if (doc.Forms[0] == null) { // "registerForm"
                                    return;
                                }

                                // 延时
                                if (_option.Task.Step1Delay > 0 && !_delaying) {
                                    _delaying = true;
                                    return;
                                }
                                else {
                                    _delaying = false;
                                }
                                step = 2;

                                // 证件种类
                                foreach (HtmlElement option in doc.Forms[0].All["sfzmmc"].All) {    // "registerForm"
                                    if (_spying) {
                                        if (option.GetAttribute("value").Equals("c", StringComparison.CurrentCultureIgnoreCase)) {
                                            option.SetAttribute("selected", "selected");
                                        }
                                        else {
                                            option.SetAttribute("selected", String.Empty);
                                        }
                                    }
                                    else {
                                        if (option.GetAttribute("value") == (string)dtFormal.Rows[formalPos]["CardType"]) {
                                            option.SetAttribute("selected", "selected");
                                        }
                                        else {
                                            option.SetAttribute("selected", String.Empty);
                                        }
                                    }
                                }

                                // 证件号码
                                if (_spying) {
                                    doc.Forms[0].All["sfzmhm"].SetAttribute("value",    // "registerForm"
                                        new Random().Next(100000000, 1000000000).ToString());
                                }
                                else {
                                    doc.Forms[0].All["sfzmhm"].SetAttribute("value",    // "registerForm"
                                       (string)dtFormal.Rows[formalPos]["CardNo"]);
                                }

                                // 车辆识别代号
                                doc.Forms[0].All["clsbdh"].SetAttribute("value", testVIN);  // "registerForm"
                                //(string)dtTest.Rows[testPos]["VIN"]);

                                // 验证码
                                if (String.IsNullOrEmpty(doc.Forms[0].All["yzm"].GetAttribute("value").ToString())) {
                                    ValidationForm form = new ValidationForm();
                                    form.ValidationImage = GetImg(doc);
                                    form.ShowDialog();
                                    doc.Forms[0].All["yzm"].SetAttribute("value", form.ValidationCode);

                                    //Image img = GetImg(doc);
                                    //string imageFile = Application.StartupPath + "\\" + Guid.NewGuid().ToString() + ".jpg";
                                    //img.Save(imageFile, ImageFormat.Jpeg);
                                    //string yzm = Marshal.PtrToStringAnsi(OCR(imageFile, -1));
                                    //doc.Forms[0].All["yzm"].SetAttribute("value", yzm);
                                    //File.Delete(imageFile);

                                    // 提交
                                    doc.Forms[0].All["type"].SetAttribute("value", "loadXh");  // "registerForm"
                                    doc.Forms[0].All["panduan"].SetAttribute("value", "sfhm");  // "registerForm"
                                    doc.Forms[0].All["step"].SetAttribute("value", "3");  // "registerForm"
                                    doc.Forms[0].All["state"].SetAttribute("value", "ok");  // "registerForm"
                                    doc.Forms[0].InvokeMember("submit");    // "registerForm"
                                }



                                //// 记录提交日期
                                //OleDbConnection conn = new OleDbConnection(Program.ConnectionString);
                                //OleDbCommand cmd = new OleDbCommand(
                                //    "UPDATE Test SET SubmitDate = @SubmitDate WHERE Id = @Id", conn);
                                //cmd.Parameters.AddWithValue("@SubmitDate", DateTime.Now.Date);
                                //cmd.Parameters.AddWithValue("@Id", (int)dtTest.Rows[testPos]["Id"]);
                                //using (conn) {
                                //    conn.Open();
                                //    cmd.ExecuteNonQuery();
                                //}

                                return;
                            }


                            //////////////////////////////////////////////////
                            //
                            // 预选号牌
                            //

                            if (doc.Body.InnerHtml.Contains("该车用该系统选过号牌") ||
                                doc.Body.InnerHtml.Contains("该车已预选号牌")) {
                                //// 将当前VIN设置为无效
                                //OleDbConnection conn = new OleDbConnection(Program.ConnectionString);
                                //OleDbCommand cmd = new OleDbCommand(
                                //    "UPDATE Test SET Invalid = True, SubmitDate = @SubmitDate WHERE Id = @Id", conn);
                                //cmd.Parameters.AddWithValue("@SubmitDate", DateTime.Now.Date);
                                //cmd.Parameters.AddWithValue("@Id", (int)dtTest.Rows[testPos]["Id"]);
                                //using (conn) {
                                //    conn.Open();
                                //    cmd.ExecuteNonQuery();
                                //}

                                //++testPos;
                                testCount = 0;

                                step = 0;
                                Restart();
                                //step = 1;
                                //webBrowser1.GoBack();
                                return;
                            }

                            if (doc.Body.InnerHtml.Contains("请输入预选号牌")) {//step == 2 && webBrowser1.Url.ToString().ToLower() == "http://" + _option.General.Domain + "/ixh/register.do") {

                                if (doc.Forms[0] == null) { // "cxForm"
                                    return;
                                }

                                // 延时
                                if (_option.Task.Step2Delay > 0 && !_delaying) {
                                    _delaying = true;
                                    return;
                                }
                                else {
                                    _delaying = false;
                                }
                                step = 3;

                                // 当前VIN测试计数
                                ++testCount;

                                if (testCount > 5) {
                                    //OleDbConnection conn = new OleDbConnection(Program.ConnectionString);
                                    //OleDbCommand cmd = new OleDbCommand(
                                    //    "UPDATE Test SET State = @State, SubmitDate = @SubmitDate WHERE Id = @Id", conn);
                                    //cmd.Parameters.AddWithValue("@State", -1);
                                    //cmd.Parameters.AddWithValue("@SubmitDate", DateTime.Now.Date);
                                    //cmd.Parameters.AddWithValue("@Id", (int)dtTest.Rows[testPos]["Id"]);
                                    //using (conn) {
                                    //    conn.Open();
                                    //    cmd.ExecuteNonQuery();
                                    //}

                                    //++testPos;
                                    //if (testPos >= dtTest.Rows.Count) {
                                    //    return;
                                    //}
                                    testCount = 0;
                                }

                                //doc.Forms["cxForm"].All["ip"].SetAttribute("value", GetMockIP());

                                // 证件种类
                                if (_spying) {
                                    doc.Forms[0].All["sfzmmc"].SetAttribute("value", "C");   // "cxForm"
                                }
                                else {
                                    doc.Forms[0].All["sfzmmc"].SetAttribute("value", "C");   // "cxForm" //(string)dtFormal.Rows[formalPos]["CardType"]);
                                }

                                // 证件号码
                                if (_spying) {
                                    doc.Forms[0].All["sfzmhm"].SetAttribute("value", new Random().Next(100000000, 1000000000).ToString());   // "cxForm"
                                }
                                else {
                                    doc.Forms[0].All["sfzmhm"].SetAttribute("value", new Random().Next(100000000, 1000000000).ToString());  // "cxForm" //(string)dtFormal.Rows[formalPos]["CardNo"]); 2011-7-17
                                }

                                // 车辆识别代号
                                doc.Forms[0].All["clsbdh"].SetAttribute("value", testVIN);  // "cxForm" //(string)dtTest.Rows[testPos]["VIN"]);

                                // 鲁B*****
                                string hphm = _spying ? (string)dtTest.Rows[testPos]["PlateNumber"] : (string)dtFormal.Rows[formalPos]["PlateNumber"];
                                if (_spying) {
                                    doc.Forms[0].All["hphm"].SetAttribute("value", (string)dtTest.Rows[testPos]["PlateNumber"]); // "cxForm"
                                }
                                else {
                                    doc.Forms[0].All["hphm"].SetAttribute("value", (string)dtFormal.Rows[formalPos]["PlateNumber"]);    // "cxForm"
                                }

                                // 验证码
                                if (String.IsNullOrEmpty(doc.Forms[0].All["yzm"].GetAttribute("value").ToString())) {
                                    ValidationForm form = new ValidationForm();
                                    form.ValidationImage = GetImg(doc);
                                    form.ShowDialog();
                                    doc.Forms[0].All["yzm"].SetAttribute("value", form.ValidationCode);

                                    //Image img = GetImg(doc);
                                    //string imageFile = Application.StartupPath + "\\" + Guid.NewGuid().ToString() + ".jpg";
                                    //img.Save(imageFile, ImageFormat.Jpeg);
                                    //string yzm = Marshal.PtrToStringAnsi(OCR(imageFile, -1));
                                    //doc.Forms[0].All["yzm"].SetAttribute("value", yzm);
                                    //File.Delete(imageFile);

                                    // 提交
                                    doc.Forms[0].All["biaoji"].SetAttribute("value", "1");  // "cxForm"
                                    doc.Forms[0].All["type"].SetAttribute("value", "netxh");  // "cxForm"
                                    doc.Forms[0].All["step"].SetAttribute("value", "4");  // "cxForm"
                                    doc.Forms[0].InvokeMember("submit");    // "cxForm"
                                }



                                return;
                            }


                            //////////////////////////////////////////////////
                            //
                            // 信息确认
                            //

                            if (doc.Body.InnerHtml.Contains("已经超出查询次数，请明天再来重新预选")) {
                                //OleDbConnection conn = new OleDbConnection(Program.ConnectionString);
                                //OleDbCommand cmd = new OleDbCommand(
                                //    "UPDATE Test SET State = @State, SubmitDate = @SubmitDate WHERE Id = @Id", conn);
                                //cmd.Parameters.AddWithValue("@State", -1);
                                //cmd.Parameters.AddWithValue("@SubmitDate", DateTime.Now.Date);
                                //cmd.Parameters.AddWithValue("@Id", (int)dtTest.Rows[testPos]["Id"]);
                                //using (conn) {
                                //    conn.Open();
                                //    cmd.ExecuteNonQuery();
                                //}

                                //++testPos;
                                testCount = 0;

                                step = 0;
                                Restart();
                                //step = 2;
                                //webBrowser1.GoBack();

                                return;
                            }

                            if (doc.Body.InnerHtml.Contains("预选失败，该号牌被预选或不存在，请重新选号")) {
                                OleDbConnection conn = new OleDbConnection(Program.ConnectionString);
                                OleDbCommand cmd = null;

                                if (_spying) {
                                    cmd = new OleDbCommand(
                                        "UPDATE Test SET State = @State WHERE Id = @Id", conn);
                                    cmd.Parameters.AddWithValue("@State", -2);
                                    //cmd.Parameters.AddWithValue("@SubmitDate", DateTime.Now.Date);
                                    cmd.Parameters.AddWithValue("@Id", (int)dtTest.Rows[testPos]["Id"]);
                                }
                                else {
                                    cmd = new OleDbCommand(
                                        "UPDATE Formal SET State = @State WHERE Id = @Id", conn);
                                    cmd.Parameters.AddWithValue("@State", -2);
                                    //cmd.Parameters.AddWithValue("@SubmitDate", DateTime.Now.Date);
                                    cmd.Parameters.AddWithValue("@Id", (int)dtFormal.Rows[formalPos]["Id"]);
                                }

                                using (conn) {
                                    conn.Open();
                                    cmd.ExecuteNonQuery();
                                }

                                switch (_option.Task.IfNumberNotExist) {
                                    case Option.IfNumberNotExist.QuickRetry:
                                        // 快速重试
                                        step = 2;
                                        webBrowser1.GoBack();
                                        break;
                                    case Option.IfNumberNotExist.Retry:
                                        // 重试
                                        if (_option.Task.IfNumberNotExistRetryTimes > 0) {
                                            // 重试N次
                                            if (ifNumberNotExistRetryTimes < _option.Task.IfNumberNotExistRetryTimes) {
                                                // 重试第X次
                                                ++ifNumberNotExistRetryTimes;
                                                Log("号牌不存在：第 " + ifNumberNotExistRetryTimes + " 次重试");
                                            }
                                            else {
                                                ifNumberNotExistRetryTimes = 0;

                                                // 继续下一个
                                                if (_spying) {
                                                    ++testPos;
                                                }
                                                else {
                                                    ++formalPos;
                                                }

                                                Log("号牌不存在：重试结束，继续下一个任务");
                                            }
                                        }
                                        else {
                                            // 一直重试下去
                                        }
                                        step = 0;
                                        Restart();
                                        break;
                                    case Option.IfNumberNotExist.Next:
                                        // 继续下一个
                                        if (_spying) {
                                            ++testPos;
                                        }
                                        else {
                                            ++formalPos;
                                        }
                                        step = 0;
                                        Restart();
                                        break;
                                }

                                return;
                            }

                            if (doc.Body.InnerHtml.Contains("您输入的号牌已被使用，下面是近似号牌")) {
                                OleDbConnection conn = new OleDbConnection(Program.ConnectionString);
                                OleDbCommand cmd = null;

                                if (_spying) {
                                    cmd = new OleDbCommand(
                                        "UPDATE Test SET State = @State WHERE Id = @Id", conn);
                                    cmd.Parameters.AddWithValue("@State", -3);
                                    //cmd.Parameters.AddWithValue("@SubmitDate", DateTime.Now.Date);
                                    cmd.Parameters.AddWithValue("@Id", (int)dtTest.Rows[testPos]["Id"]);
                                }
                                else {
                                    cmd = new OleDbCommand(
                                        "UPDATE Formal SET State = @State WHERE Id = @Id", conn);
                                    cmd.Parameters.AddWithValue("@State", -3);
                                    //cmd.Parameters.AddWithValue("@SubmitDate", DateTime.Now.Date);
                                    cmd.Parameters.AddWithValue("@Id", (int)dtFormal.Rows[formalPos]["Id"]);
                                }

                                using (conn) {
                                    conn.Open();
                                    cmd.ExecuteNonQuery();
                                }

                                switch (_option.Task.IfNumberHasBeUsed) {
                                    case Option.IfNumberHasBeUsed.QuickRetry:
                                        // 快速重试
                                        step = 2;
                                        webBrowser1.GoBack();
                                        break;
                                    case Option.IfNumberHasBeUsed.Retry:
                                        // 重试
                                        if (_option.Task.IfNumberHasBeUsedRetryTimes > 0) {
                                            // 重试N次
                                            if (ifNumberHasBeUsedRetryTimes < _option.Task.IfNumberHasBeUsedRetryTimes) {
                                                // 重试第X次
                                                ++ifNumberHasBeUsedRetryTimes;
                                                Log("号牌已被预约：第 " + ifNumberHasBeUsedRetryTimes + " 次重试");
                                            }
                                            else {
                                                ifNumberHasBeUsedRetryTimes = 0;

                                                // 继续下一个
                                                if (_spying) {
                                                    ++testPos;
                                                }
                                                else {
                                                    ++formalPos;
                                                }

                                                Log("号牌已被预约：重试结束，继续下一个任务");
                                            }
                                        }
                                        else {
                                            // 一直重试下去
                                        }
                                        step = 0;
                                        Restart();
                                        break;
                                    case Option.IfNumberHasBeUsed.Next:
                                        // 继续下一个
                                        if (_spying) {
                                            ++testPos;
                                        }
                                        else {
                                            ++formalPos;
                                        }
                                        step = 0;
                                        Restart();
                                        break;
                                }

                                return;
                            }

                            //if (step == 3){// && webBrowser1.Url.ToString().ToLower() == "http://" + _option.General.Domain + "/ixh/cx.do") {

                            if (doc.Body.InnerHtml.Contains("鲁B" + (_spying ? (string)dtTest.Rows[testPos]["PlateNumber"] : (string)dtFormal.Rows[formalPos]["PlateNumber"]))) {
                                if (doc.Forms[0] == null) {  // "cxForm"
                                    return;
                                }

                                if (!_spying) {
                                    // 这个号可以预约！

                                    // 延时
                                    if (_option.Task.Step3Delay > 0 && !_delaying) {
                                        _delaying = true;
                                        return;
                                    }
                                    else {
                                        _delaying = false;
                                    }
                                    step = 4;

                                    doc.Forms[0].All["biaoji"].SetAttribute("value", "2");  // "cxForm"
                                    doc.Forms[0].All["type"].SetAttribute("value", "netxh");    // 2011-11-8
                                    doc.Forms[0].All["step"].SetAttribute("value", "4");    // 2011-11-8
                                    doc.Forms[0].All["clsbdh"].SetAttribute("value", (string)dtFormal.Rows[formalPos]["VIN"]);  // "cxForm"
                                    doc.Forms[0].All["sfzmmc"].SetAttribute("value", (string)dtFormal.Rows[formalPos]["CardType"]);  // 2011-7-17   // "cxForm"
                                    doc.Forms[0].All["sfzmhm"].SetAttribute("value", (string)dtFormal.Rows[formalPos]["CardNo"]);    // 2011-7-17   // "cxForm"
                                    doc.Forms[0].InvokeMember("submit");    // "cxForm"
                                }
                                else {
                                    Log("鲁B" + (string)dtTest.Rows[testPos]["PlateNumber"] + " 可以预约");

                                    OleDbConnection conn = new OleDbConnection(Program.ConnectionString);
                                    OleDbCommand cmd = new OleDbCommand(
                                        "UPDATE Test SET State = @State, SubmitDate = @SubmitDate WHERE Id = @Id", conn);
                                    cmd.Parameters.AddWithValue("@State", 1);
                                    cmd.Parameters.AddWithValue("@SubmitDate", DateTime.Now.ToString());
                                    cmd.Parameters.AddWithValue("@Id", (int)dtTest.Rows[testPos]["Id"]);
                                    using (conn) {
                                        conn.Open();
                                        cmd.ExecuteNonQuery();
                                    }

                                    ++succeedCount;
                                    ++testPos;
                                    step = 0;
                                    Restart();
                                }

                                return;
                            }

                            //    // 提交想选的号牌后遇到未知页面
                            //    step = 0;
                            //    Restart();
                            //    return;
                            //}


                            //////////////////////////////////////////////////
                            //
                            // 选号完成
                            //

                            //if (step == 4){// && webBrowser1.Url.ToString().ToLower() == "http://" + _option.General.Domain + "/ixh/cx.do") {
                            if (doc.Body.InnerHtml.Contains("预选号成功")) {
                                Log("鲁B" + (string)dtFormal.Rows[formalPos]["PlateNumber"] + " 预选号成功");

                                // 将正式数据库中的当前号码标记为“预选号成功”
                                OleDbConnection conn = new OleDbConnection(Program.ConnectionString);
                                OleDbCommand cmd = new OleDbCommand(
                                    "UPDATE Formal SET State = @State, SubmitDate = @SubmitDate WHERE Id = @Id", conn);
                                cmd.Parameters.AddWithValue("@State", 1);
                                cmd.Parameters.AddWithValue("@SubmitDate", DateTime.Now.ToString());
                                cmd.Parameters.AddWithValue("@Id", (int)dtFormal.Rows[formalPos]["Id"]);
                                using (conn) {
                                    conn.Open();
                                    cmd.ExecuteNonQuery();
                                }

                                dtFormal.Rows.RemoveAt(formalPos);

                                ++succeedCount;
                                //++formalPos;
                                //testing = true;    // 转回测试模式
                                // 延时
                                if (_option.Task.Step4Delay > 0 && !_delaying) {
                                    _delaying = true;
                                    return;
                                }
                                else {
                                    _delaying = false;
                                }
                                step = 0;
                                Restart();
                                return;
                            }
                            //}

                        }
                        catch (Exception ex) {
                            //MessageBox.Show(ex.ToString());
                            //_running = false;

                            Log(ex.Message);
                            Restart();

                            //needDelay = false;
                            return;
                        }

                        // 遇到未知页面
                        if (_running && _documentCompleted) {
                            //Log("遇到未知页面");

                            //
                            // 记录未知页面

                            if (!Directory.Exists(Application.StartupPath + "/UnknownPages")) {
                                Directory.CreateDirectory(Application.StartupPath + "/UnknownPages");
                            }
                            string unknownPageFileName = Application.StartupPath + "/UnknownPages/" +
                                String.Format("{0:0000}-{1:00}-{2:00}-{3:00}-{4:00}-{5:00}-{6:000}.html",
                                    DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day,
                                    DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond);
                            using (FileStream fs = new FileStream(unknownPageFileName, FileMode.Create)) {
                                byte[] buffer = new byte[webBrowser1.DocumentStream.Length];
                                webBrowser1.DocumentStream.Read(buffer, 0, buffer.Length);
                                fs.Write(buffer, 0, buffer.Length);
                            }

                            switch (_option.Task.IfFoundUnknownPage) {
                                case PlateNumber.Option.IfFoundUnknownPage.Pause:
                                    Log("遇到未知页面，当前任务已暂停");
                                    break;
                                case PlateNumber.Option.IfFoundUnknownPage.Stop:
                                    Log("遇到未知页面，任务被终止");
                                    Stop();
                                    break;
                                case PlateNumber.Option.IfFoundUnknownPage.Retry:
                                    Log("遇到未知页面，重新开始当前任务");
                                    step = 0;
                                    //Restart();
                                    webBrowser1.Navigate("http://" + _option.General.Domain + "/ixh/ywlxqd.jsp");
                                    break;
                                case PlateNumber.Option.IfFoundUnknownPage.Next:
                                    Log("遇到未知页面，继续下一个任务");
                                    step = 0;
                                    if (_spying) {
                                        ++testPos;
                                    }
                                    else {
                                        ++formalPos;
                                    }
                                    //Restart();
                                    webBrowser1.Navigate("http://" + _option.General.Domain + "/ixh/ywlxqd.jsp");
                                    break;
                            }
                        }
                    })); // 真正干活的地方

                    if (_delaying) {
                        switch (step) {
                            case 0:
                                Delay(_option.Task.Step0Delay);
                                break;
                            case 1:
                                Delay(_option.Task.Step1Delay);
                                break;
                            case 2:
                                Delay(_option.Task.Step2Delay);
                                break;
                            case 3:
                                Delay(_option.Task.Step3Delay);
                                break;
                            case 4:
                                Delay(_option.Task.Step4Delay);
                                break;
                            default:
                                _delaying = false;
                                break;
                        }
                    }
                } // if _documentCompleted

                Thread.Sleep(200);
            } // while


            if (this == null || this.IsDisposed) {
                return;
            }
            this.Invoke(new Worker(delegate() {
                Stop();
                //MessageBox.Show(this, "任务完成，预约成功 " + succeedCount + " 个车牌号。",
                //    Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
                Log("任务结束，共" + (_spying ? "探测" : "预选") + "到 " + succeedCount + " 个车牌号");

                //toolStripButton1.Image = imageList1.Images[0];
                //toolStripButton4.Enabled = true;
                Stop();

                MessageBeep(0);
            }));
        }

        #endregion

        private void tsbRedial_Click(object sender, EventArgs e) {
            Redial();
            _currentIPUsingTimes = 1;
        }

        // 获取验证码
        private Image GetImg(HtmlDocument doc) {
            Image returnImage = null;
            try {

                IHTMLDocument2 document = (IHTMLDocument2)doc.DomDocument;
                foreach (IHTMLElement image in document.images) {
                    if (image.outerHTML.Contains("验证码")) {
                        IHTMLControlElement img = (IHTMLControlElement)image;
                        HTMLBody body = (HTMLBody)document.body;
                        IHTMLControlRange range = (IHTMLControlRange)body.createControlRange();
                        range.add(img);
                        range.execCommand("Copy", false, null);
                        Image clipImage = Clipboard.GetImage();
                        returnImage = new Bitmap(clipImage);//, new Size(clipImage.Width * 2, clipImage.Height * 2));
                        break;
                    }
                }
            }
            catch (Exception ex) {
                //MessageBox.Show(ex.ToString());
            }

            return returnImage;
        }
    }
}
